home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ShareWare OnLine 2
/
ShareWare OnLine Volume 2 (CMS Software)(1993).iso
/
os2
/
pmf300.zip
/
PMFLOPPY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-06
|
20KB
|
666 lines
/*
pmfloppy.c
main program
PM based disk utility. Use separate threads for disk actions to
prevent slowing up PM too much. Use huge memory allocation for
single pass reads.
G. Bryant, 1990,1993
Delta Music Systems
Released to the public domain
Change Log
8-Jun-90 Correct array bounds violation in FreeThread
9-Jun-90 Correct the EXPORTS statement in pmfloppy.def
15-Jun-90 Remove extraneous defines
5-Feb-93 Port to OS/2 2.0-C Set/2
*/
#define INCL_PM
#define INCL_BASE
#define INCL_DOSDEVIOCTL
#define INCL_DOSPROCESS
#define INCL_WININPUT
#include <os2.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <process.h>
#include "pmfloppy.h"
#include "DskIm.h"
// prototypes for current file
MRESULT EXPENTRY ClientWndProc(HWND, ULONG, MPARAM, MPARAM);
VOID Panic(PCH, ULONG);
VOID DisplayStatus(HWND, HPS, ULONG);
VOID DisplayDone(HWND , HPS, ULONG);
VOID FreeThread(ULONG);
VOID DisplayImageStat(HWND, HPS);
VOID PutBox(PSZ, PSZ);
// prototypes from copydlgs.c
extern FNWP ReadDlgProc;
extern FNWP WriteDlgProc;
extern FNWP DeleteDlgProc;
extern FNWP LoadDlgProc;
extern FNWP SaveDlgProc;
extern FNWP CompDlgProc;
extern FNWP AboutDlgProc;
// prototypes from dskcpy.c
extern VOID _System readsource(ULONG);
extern VOID _System writetarget(ULONG);
extern VOID _System LoadImage(ULONG);
extern VOID _System SaveImage(ULONG);
extern VOID _System CompImages(ULONG);
/* GLOBAL VARIABLES */
// PM vbls
HAB hab;
HMQ hmq;
HWND hWndFrame ;
static CHAR szClientClass[]="PMFloppy";
ULONG ctldata = FCF_STANDARD & ~FCF_TASKLIST;
HWND hWndClient;
HWND hwndDeskTop;
QMSG qmsg;
LONG CharHeight;
LONG CharWidth;
// User response vbls
DskImage ImageBuffers[NUM_IMAGES];
USHORT BufferNum; // only use in foreground thread
USHORT CompNum; // only use in foreground thread
// Thread variables
ThreadContext tcThBufs[NUM_THREADS];
int main(void)
{
SWCNTRL swctl;
PID pid;
hab = WinInitialize(0);
hmq = WinCreateMsgQueue(hab, 0);
hwndDeskTop = WinQueryDesktopWindow(hab, NULLHANDLE);
if (!WinRegisterClass(hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0))
return(0);
hWndFrame = WinCreateStdWindow(HWND_DESKTOP,
WS_VISIBLE,
&ctldata,
szClientClass,
"Floppy Disk Utility",
0L,
0,
IDR_PMFLOPPY,
&hWndClient);
if (hWndFrame != NULLHANDLE)
{
WinQueryWindowProcess(hWndFrame, &pid, NULL);
swctl.hwnd = hWndFrame;
swctl.hwndIcon = NULLHANDLE;
swctl.hprog = NULLHANDLE;
swctl.idProcess = pid;
swctl.idSession = 0;
swctl.uchVisibility = SWL_VISIBLE;
swctl.fbJump = SWL_JUMPABLE;
swctl.szSwtitle[0] = '\0';
WinAddSwitchEntry(&swctl);
while ( WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0) )
WinDispatchMsg(hab, &qmsg);
WinDestroyWindow(hWndFrame);
}
WinDestroyMsgQueue(hmq);
WinTerminate(hab);
return(0);
} /* main */
// ClientWndProc - main window processing
//
// note: UM messages are User-defined (in pmfloppy.h).
// all UM messages use mp2 to indicate the drive the message concerns,
// and mp1 is data specific to that message. Then UM_xxxMSG is a
// generic msg. It is currently only used for DONE messages. If I
// need more, set up some magic numbers and pass them through mp1.
//
MRESULT EXPENTRY ClientWndProc(HWND hwnd,
ULONG id,
MPARAM mp1,
MPARAM mp2)
{
HPS hPS;
HWND hMenu;
CHAR szTxtBuf[MAXMSGLEN];
FONTMETRICS fm;
ULONG curBuff;
USHORT gotSource;
BOOL DriveActive;
ULONG curTh;
RECTL rctPaint;
switch (id)
{
case WM_CREATE:
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
ImageBuffers[curBuff].BufferName[0] = '\0';
for (curTh=0;curTh < NUM_THREADS;curTh++)
{
tcThBufs[curTh].ThID = 0;
tcThBufs[curTh].ImageNumber = NUM_IMAGES+1;
tcThBufs[curTh].CompNumber = NUM_IMAGES+1;
}
hPS = WinGetPS(hwnd);
GpiQueryFontMetrics(hPS, (long)sizeof(fm), &fm);
CharHeight = fm.lMaxBaselineExt;
CharWidth = fm.lMaxCharInc;
WinReleasePS(hPS);
break;
case WM_PAINT:
hPS = WinGetPS(hwnd);
GpiErase(hPS);
WinQueryUpdateRect(hwnd,&rctPaint);
DisplayImageStat(hwnd, hPS);
WinValidateRect(hwnd, &rctPaint, FALSE);
WinReleasePS(hPS);
break;
case WM_COMMAND:
switch (COMMANDMSG(&id)->cmd)
{
case IDM_READ:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,ReadDlgProc,0,READ_DLG,NULL))
{
// send off thread to read
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS)
{
tcThBufs[curTh].ImageNumber = BufferNum;
if (DosCreateThread(&(tcThBufs[curTh].ThID),
&readsource,
curTh,
0,
STACK_SIZE))
{
PutBox("Drive Read","DosCreateThread failed.");
return FALSE;
} /* if can't create the thread. */
}
else
{
PutBox("Drive Read","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_WRITE:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,WriteDlgProc,0,WRITE_DLG,NULL))
{
// send off thread to write
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS)
{
tcThBufs[curTh].ImageNumber = BufferNum;
if (DosCreateThread(&(tcThBufs[curTh].ThID),
&writetarget,
curTh,
0,
STACK_SIZE))
{
PutBox("Drive Write","DosCreateThread failed.");
return FALSE;
} /* if can't create the thread. */
}
else
{
PutBox("Drive Write","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_ABOUT:
WinDlgBox(HWND_DESKTOP,hWndFrame,AboutDlgProc,0,ABOUT_DLG,NULL);
break;
case IDM_DELETE:
WinDlgBox(HWND_DESKTOP,hWndFrame,DeleteDlgProc,0,DELETE_DLG,NULL);
hPS = WinGetPS(hwnd);
GpiErase(hPS);
DisplayImageStat(hwnd, hPS);
WinReleasePS(hPS);
break;
case IDM_LOAD:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,LoadDlgProc,0,LOAD_DLG,NULL))
{
// send off thread to load
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS)
{
tcThBufs[curTh].ImageNumber = BufferNum;
if (DosCreateThread(&(tcThBufs[curTh].ThID),
&LoadImage,
curTh,
0,
STACK_SIZE))
{
PutBox("Image Load","DosCreateThread failed.");
return FALSE;
} /* if can't create the thread. */
}
else
{
PutBox("Image Load","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_SAVE:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,SaveDlgProc,0,SAVE_DLG,NULL))
{
// send off thread to save
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS)
{
tcThBufs[curTh].ImageNumber = BufferNum;
if (DosCreateThread(&(tcThBufs[curTh].ThID),
&SaveImage,
curTh,
0,
STACK_SIZE))
{
PutBox("Image Save","DosCreateThread failed.");
return FALSE;
} /* if can't create the thread. */
}
else
{
PutBox("Image Save","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
case IDM_COMP:
if (WinDlgBox(HWND_DESKTOP,hWndFrame,CompDlgProc,0,COMP_DLG,NULL))
{
// send off thread to compare
for (curTh=0;
(curTh < NUM_THREADS) && (tcThBufs[curTh].ThID != 0);
curTh++) ;
if (curTh < NUM_THREADS)
{
tcThBufs[curTh].ImageNumber = BufferNum;
tcThBufs[curTh].CompNumber = CompNum;
if (DosCreateThread(&(tcThBufs[curTh].ThID),
&CompImages,
curTh,
0,
STACK_SIZE))
{
PutBox("Image Compare","DosCreateThread failed.");
return FALSE;
} /* if can't create the thread. */
}
else
{
PutBox("Image Compare","Out of program thread resources.");
return FALSE;
} /* if can't create the thread. */
}
break;
}
break;
case WM_INITMENU:
//set the allowable menu choices.
hMenu = WinWindowFromID(hWndFrame,FID_MENU);
// If we don't have anything to write, disable the write, save, and
// delete menus
gotSource = 0;
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
{
if (ImageBuffers[curBuff].Percent == 100) gotSource++;
}
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_WRITE,TRUE),
MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_SAVE,TRUE),
MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_DELETE,TRUE),
MPFROM2SHORT(MIA_DISABLED,gotSource ? 0 : MIA_DISABLED));
WinSendMsg(hMenu,MM_SETITEMATTR,
MPFROM2SHORT(IDM_COMP,TRUE),
MPFROM2SHORT(MIA_DISABLED,(gotSource > 1) ? 0 : MIA_DISABLED));
break;
case UM_STATUS:
curTh = LONGFROMMP(mp1);
hPS = WinGetPS(hwnd);
DisplayStatus(hwnd, hPS, curTh);
WinReleasePS(hPS);
break;
case UM_DONE:
curTh = LONGFROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
hPS = WinGetPS(hwnd);
WinAlarm(HWND_DESKTOP,WA_NOTE);
DisplayDone(hwnd, hPS,curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case UM_ERROR:
curTh = LONGFROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
switch (ImageBuffers[curBuff].Busy)
{
case BUSY_READ:
sprintf(szTxtBuf,"Read Error on drive %c", ImageBuffers[curBuff].DriveID[0]);
break;
case BUSY_WRITE:
sprintf(szTxtBuf,"Write Error on drive %c", ImageBuffers[curBuff].DriveID[0]);
break;
case BUSY_LOAD:
sprintf(szTxtBuf,"Load Error on drive %s", ImageBuffers[curBuff].FileName);
break;
case BUSY_SAVE:
sprintf(szTxtBuf,"Save Error on file %s", ImageBuffers[curBuff].FileName);
break;
}
Panic(szTxtBuf, tcThBufs[curTh].ErrorCode);
hPS = WinGetPS(hwnd);
DisplayStatus(hwnd, hPS, curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case UM_COMPOK:
curTh = LONGFROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
WinAlarm(HWND_DESKTOP,WA_NOTE);
PutBox("Image Compare","Images are identical!");
hPS = WinGetPS(hwnd);
DisplayDone(hwnd, hPS,curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case UM_COMPERR:
curTh = LONGFROMMP(mp1);
curBuff = tcThBufs[curTh].ImageNumber;
WinAlarm(HWND_DESKTOP,WA_WARNING);
PutBox("Image Compare","Images are different");
hPS = WinGetPS(hwnd);
DisplayDone(hwnd, hPS,curBuff);
FreeThread(curTh);
WinReleasePS(hPS);
break;
case WM_CLOSE:
DriveActive = FALSE;
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
if (ImageBuffers[curBuff].Busy) DriveActive = TRUE;
if (DriveActive)
{
if (MBID_OK != WinMessageBox(HWND_DESKTOP,
hWndFrame,
"are you sure you want to quit?",
"A Drive is still running - ",
0,
MB_OKCANCEL | MB_QUERY))
break;
}
// else just fall through to default to get to the default proc
default:
return(WinDefWindowProc(hwnd, id, mp1, mp2));
} /* switch id */
return 0;
} /* clientwndproc */
// Panic -- Put up a message box with an error message.
//
// Inputs: pszCaption -- Caption text for message box
//
// Returns: 1L, for error signalling from window procedures.
VOID Panic(PCH pszCaption, ULONG ErrorNum)
{
CHAR buf[1024];
ULONG cbBuf;
if (ErrorNum == DSKIM_ERROR_WRONG_FORMAT)
sprintf(buf, "Error - target disk has incorrect format");
else if (ErrorNum == DSKIM_ERROR_WRONG_FILE)
sprintf(buf, "Error - file is not in correct format");
else if (DosGetMessage(NULL, 0, buf, 1024, ErrorNum, "oso001.msg", &cbBuf))
{
sprintf(buf, "SYS%04d: error text unavailable", ErrorNum);
cbBuf = 31;
}
buf[cbBuf] = (char)0;
WinQueryFocus(HWND_DESKTOP);
WinAlarm(HWND_DESKTOP, WA_ERROR);
PutBox(pszCaption, buf);
return;
} // panic
// DisplayStatus - Display the status for the drive in the PS
//
// in: usPct Percent done
// Drive drive letter
// hwnd window handle to display on
// op operation (eg read, write)
//
VOID DisplayStatus(HWND hwnd, HPS hPS, ULONG curTh) {
RECTL rctStart;
CHAR szTxtBuf[MAXMSGLEN];
CHAR op[10];
CHAR Object[6];
CHAR Device[80];
USHORT curBuff;
USHORT compBuff;
curBuff = tcThBufs[curTh].ImageNumber;
compBuff = tcThBufs[curTh].CompNumber;
switch (ImageBuffers[curBuff].Busy) {
case BUSY_READ:
strcpy(op,"reading");
strcpy(Object,"Drive");
Device[0] = ImageBuffers[curBuff].DriveID[0];
Device[1] = '\0';
break;
case BUSY_WRITE:
strcpy(op,"writing");
strcpy(Object,"Drive");
Device[0] = ImageBuffers[curBuff].DriveID[0];
Device[1] = '\0';
break;
case BUSY_LOAD:
strcpy(op,"loading");
strcpy(Object,"file");
strcpy(Device,ImageBuffers[curBuff].FileName);
break;
case BUSY_SAVE:
strcpy(op,"saving");
strcpy(Object,"file");
strcpy(Device,ImageBuffers[curBuff].FileName);
break;
case BUSY_COMP:
strcpy(op,"comparing");
strcpy(Object,"image");
strcpy(Device,ImageBuffers[compBuff].BufferName);
break;
}
rctStart.xLeft = 5L;
rctStart.xRight = 5L + (CharWidth * MAXMSGLEN);
rctStart.yBottom = (curBuff * CharHeight) + 5;
rctStart.yTop = rctStart.yBottom + CharHeight;
sprintf(szTxtBuf,
"Image %s %s %s %s (%d%% complete)",
ImageBuffers[curBuff].BufferName,
op,
Object,
Device,
ImageBuffers[curBuff].Percent);
WinDrawText(hPS, -1, szTxtBuf, &rctStart, CLR_NEUTRAL, CLR_BACKGROUND,
DT_LEFT | DT_ERASERECT);
WinValidateRect(hwnd, &rctStart, FALSE);
return;
}
// DisplayDone - Display an operation complete
//
// in: Drive drive letter
// hwnd window handle to display on
// op operation (eg read, write)
//
VOID DisplayDone(HWND hwnd, HPS hPS, ULONG curBuff) {
RECTL rctStart;
CHAR szTxtBuf[MAXMSGLEN];
rctStart.xLeft = 5L;
rctStart.xRight = 5L + (CharWidth * MAXMSGLEN);
rctStart.yBottom = (curBuff * CharHeight) + 5;
rctStart.yTop = rctStart.yBottom + CharHeight;
sprintf(szTxtBuf, "Image %s is full", ImageBuffers[curBuff].BufferName);
WinDrawText(hPS, -1, szTxtBuf, &rctStart, CLR_NEUTRAL, CLR_BACKGROUND,
DT_LEFT | DT_ERASERECT);
WinValidateRect(hwnd, &rctStart, FALSE);
return;
}
// FreeThread - clean up after a child thread
//
// in: curTh - Thread to clean up
//
VOID FreeThread(ULONG curTh) {
ULONG curBuff;
ULONG compBuff;
// sit here until the thread is gone
DosWaitThread(&(tcThBufs[curTh].ThID), DCWW_WAIT);
curBuff = tcThBufs[curTh].ImageNumber;
compBuff = tcThBufs[curTh].CompNumber;
tcThBufs[curTh].ThID = 0;
tcThBufs[curTh].ImageNumber = NUM_IMAGES+1;
tcThBufs[curTh].CompNumber = NUM_IMAGES+1;
tcThBufs[curTh].ErrorCode = 0;
ImageBuffers[curBuff].Busy = FALSE;
if (compBuff < NUM_IMAGES) ImageBuffers[compBuff].Busy = FALSE;
return;
}
VOID DisplayImageStat(HWND hwnd, HPS hPS) {
RECTL rctStart;
RECTL rctPaint;
ULONG curBuff;
WinQueryWindowRect(hwnd,&rctPaint);
if (ImageBuffers[0].BufferName[0] == '\0') {
rctStart.xLeft = 5L;
rctStart.xRight = 5L + (CharWidth * 16);
rctStart.yBottom = 5L;
rctStart.yTop = rctStart.yBottom + CharHeight;
WinDrawText(hPS,
-1,
"No images in use",
&rctStart,
CLR_NEUTRAL,
CLR_BACKGROUND,
DT_LEFT | DT_ERASERECT);
}
else {
for (curBuff=0;curBuff < NUM_IMAGES;curBuff++)
if (ImageBuffers[curBuff].BufferName[0] != '\0') {
if (ImageBuffers[curBuff].Busy) DisplayStatus(hwnd, hPS, curBuff);
else DisplayDone(hwnd,hPS, curBuff);
}
}
return;
}
//
// Put the messages in an application modal message box
//
VOID PutBox(PSZ msg1, PSZ msg2) {
WinMessageBox(HWND_DESKTOP,
hWndFrame,
msg2,
msg1,
0,
MB_OK | MB_ICONEXCLAMATION);
return;
} // PutBox